package linestrategy

import (
	"codejy/analysis"
	"codejy/analysis/lineanalysis"
	"codejy/globalfunc"
	"codejy/structdef"
	"codejy/utils"
	"fmt"
	"strings"
)

// 定义函数和属性调用策略 ,多级调用
type UniteCallChaiStrategy struct {
}

// 注册策略
func init() {
	RegisterStrategy(&UniteCallChaiStrategy{})
	globalfunc.RegisterFuncAll("UniteCallChaiExecute", UniteCallChaiExecute)
}

// 判断是否是函数调用
func (f *UniteCallChaiStrategy) getId() int {
	return lineanalysis.UniteCallChain
}

func (f *UniteCallChaiStrategy) Execute(threadStore *structdef.ThreadStore) {
	content := threadStore.Code.LineContent
	UniteCallChaiExecute(threadStore, content)
}

// 多级调用  a.b.c().d().e
func UniteCallChaiExecute(threadStore *structdef.ThreadStore, content string) string {
	replace, str := utils.FuncBracketsReplace(content)
	//按照.号分割
	split := strings.Split(str, ".")
	length := len(split)
	for i := 0; i < length; i++ {
		code := split[i]
		var value string
		var skip = i
		//替换回去
		code = utils.FuncBracketsReplaceBack(replace, code)
		//如果开头是global,那么就将下一个拼接
		if strings.HasPrefix(code, "global") {
			code2 := utils.FuncBracketsReplaceBack(replace, split[i+1])
			code = code + "." + code2
			value = globalfunc.ExecuteFunc("AssignmentStrategyMode", threadStore, code).(string)
			skip = i + 1
		} else {
			value = globalfunc.ExecuteFunc("AssignmentStrategyMode", threadStore, code).(string)
		}
		//判断是最后一个元素
		if i == length-1 {
			return value
		}
		if skip+1 < length {
			if value == "" {
				var errorStr = fmt.Sprintf("调用链中第%d个元素调用错误,因为返回值为空,请检查调用链的返回值是否正确,错误行代码:%s,错误代码为:%s", i, content, code)
				panic(errorStr)
			}
			//判断返回值是否是实例地址
			if !analysis.IsInstanceAddress(value) {
				var errorStr = fmt.Sprintf("调用链中第%d个元素调用错误,因为返回值不是实例,请检查调用链的返回值是否正确,错误行代码:%s,错误代码为:%s", i, content, code)
				panic(errorStr)
			}
		}
		if skip == i {

			//将值和下一个元素拼接,给下一个
			if i+1 < length {
				value = value + "." + split[i+1]
				split[i+1] = value
			}
		}
		i = skip
	}
	return ""
}
